package model;

import java.io.Serializable;
import java.util.Comparator;

import model.util.ModelException;



@SuppressWarnings("serial")
public class Film extends ModelBase implements Serializable, Comparable<Film> 
{

  private String name;
  private String hauptdarsteller;
  private String genre;
  private int laenge;
  private Datentraeger datentraeger;
  private int anzahl = 0;
  private Long datID = null;
  private FilmInfo info =new FilmInfo();

  public Film(Long id, String name, String hauptdarsteller, String genre, int laenge, Long datentraegerId) 
  {
	setId(id);
    setName(name);
    setHauptdarsteller(hauptdarsteller);
    setGenre(genre);
    setLaenge(laenge);
    this.datID = datentraegerId;
    initFilmInfo();
  }
  
  public Film(Long id, String name, String hauptdarsteller, String genre, int laenge) 
  {
	setId(id);
    setName(name);
    setHauptdarsteller(hauptdarsteller);
    setGenre(genre);
    setLaenge(laenge);
    initFilmInfo();
  }



//  public Film(String name, String hauptdarsteller, String genre) 
//  {
//    this(name, hauptdarsteller, genre, 120);
//  }

  public Film(String name, String hauptdarsteller, String genre, int laenge) 
  {
	    setName(name);
	    setHauptdarsteller(hauptdarsteller);
	    setGenre(genre);
	    setLaenge(laenge);
	    initFilmInfo();
		
  }

  public Film(String name) 
  {
	    setName(name);
	    initFilmInfo();
		
  }


  public int getAnzahl()
  {
		return anzahl;
  }
  
  public Film setDatentraegerId(Long datID)
	{
		if (datID == null)
			throw new ModelException("DatentraegerId must not be null!");
		this.datID = datID;
		return this;
	}

	public void setDatentraegerId(String datId)
	{
		try{
			setDatentraegerId(Long.parseLong(datId));
		}catch(NumberFormatException e){
			throw new ModelException("NumberFormatException at setDatentraegerId(String) in Produkt");
		}
	}
    public Long getDatentraegerID()
	{
		return datID;
	}
  
    public void setName(String name) 
    {
      if (name == null || name.trim().length() == 0 || name.trim().length() > 20) 
      {
    	throw new IllegalArgumentException("name must not be null, empty or longer than 20 characters!"); 
      }
      this.name = name.trim();
    }

    public String getName() 
    {
      return name;
    }

    public void setHauptdarsteller(String hauptdarsteller) 
    {
      if (hauptdarsteller == null || hauptdarsteller.trim().length() == 0 || hauptdarsteller.trim().length() > 30)
      {
    	throw new IllegalArgumentException("hauptdarsteller must not be null, empty or longer than 30 characters!");
      }
      this.hauptdarsteller = hauptdarsteller.trim();
    }

    public String getHauptdarsteller() 
    {
      return hauptdarsteller;
    }

    public void setGenre(String genre) 
    {
	  if (genre == null || genre.trim().length() == 0 || genre.trim().length() > 30)
	  {
		throw new IllegalArgumentException("genre must not be null, empty or longer than 30 characters!");
	  }
	  this.genre = genre.trim();
    }

    public String getGenre() 
    {
      return genre;
    }

    public void setLaenge(int laenge) 
    {
	  if (laenge <= 0 || laenge >= 500)
	  {
		  throw new IllegalArgumentException("laenge must not be negative or zero!");
	  }
	  this.laenge = laenge;
    }

    public int getLaenge()
    {
      return laenge;
    }
  
    public void removeDatentraeger()
	{
		this.datID=null;
		info.setFilmDat("nicht zugeordnet");		
	}

	public Film anzahlErhoehen(int anz)
	{
		if (anz < 0 || anz >= 1000000)
			throw new ModelException("anz has to be between 0 and 1000000!");
		if ((this.anzahl + anz) >= 1000000)
			throw new ModelException("anz storagecapacity overflow!");
		this.anzahl = this.anzahl + anz;
		return this;
	}

	public Film anzahlVermindern(int anz)
	{
		if (anz <= 0 || anz >= 1000000)
			throw new ModelException("anz has to be between 1 and 1000000!");
		if ((this.anzahl - anz) < 0)
			throw new ModelException("anz must not be greater than this.anz!");
		this.anzahl = this.anzahl - anz;
		return this;
	}
	
	public FilmInfo getInfo(){
		return info;
	}

    public Film setDatentraeger(Datentraeger datentraeger)
    {
  	  if (datentraeger == null)
  	  {
		throw new IllegalArgumentException("datentraeger must not be null");
  	  }
	  this.datentraeger = datentraeger;
	  return this;
    }  
  
    public Datentraeger getDatentraeger()
    {
	    return datentraeger;
    }
  
    @Override
    public int compareTo(Film other)
    {
      return name.compareTo(other.getName());
    }
    
    private void initFilmInfo()
    {
    	info.setFilmId(""+getId());
    	info.setName(name);
    	info.setHptDst(hauptdarsteller);
    	info.setGenre(genre);
    	info.setLaenge(""+laenge);
    }
    
    public void initDatInfo()
    {
    	info.setFilmDat(datentraeger.getName());
    }

    public static final class HauptdarstellerNameComparator implements Comparator<Film> 
    {

      @Override
      public int compare(Film left, Film right)
      {
        int result;
        if ((result = left.getHauptdarsteller().compareTo(right.getHauptdarsteller())) == 0)
        {
       	  result = left.getName().compareTo(right.getName());
        }
        return result;
        }

    }
  
    public static final class FilmNameComparator implements Comparator<Film> 
    {

      @Override
      public int compare(Film left, Film right)
      {
        int result;
        if ((result = left.getName().compareTo(right.getName())) == 0)
        {
     	  result = left.getName().compareTo(right.getName());
        }
        return result;
      }

    }

    @Override
    public String toString()
    {
      return String.format("%s {name=%s, hauptdarsteller=%s, genre=%s, laenge=%d}%n", getClass().getSimpleName(), name, hauptdarsteller, genre, laenge);
    }

    @Override
    public int hashCode() 
    {
      final int prime = 31;
      int result = 1;
      result = prime * result + (name == null ? 0 : name.hashCode());
      result = prime * result + (hauptdarsteller == null ? 0 : hauptdarsteller.hashCode());
      result = prime * result + (genre == null ? 0 : genre.hashCode());
      result = prime * result + laenge;
      return result;
    }
  
 
    public boolean equals(Object obj)
	{
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		Film other = (Film) obj;
		if (anzahl != other.anzahl)
			return false;
		if (name == null)
		{
			if (other.name != null)
				return false;
		} else if (!name.equals(other.name))
			return false;
		return super.equals(obj);
	}
	

	public class FilmInfo
	{
		private String filmId;
		private String name;
		private String hptDst;
		private String genre;
		private String laenge;
		private String filmDat="nicht zugeordnet";
		
		
		/**
		 * @return
		 */
		public String getFilmId()
		{
			return filmId;
		}
		/**
		 * @param filmId
		 */
		public void setFilmId(String filmId)
		{
			this.filmId = filmId;
		}
		/**
		 * @return the name
		 */
		public String getName() {
			return name;
		}
		/**
		 * @param name the name to set
		 */
		public void setName(String name) {
			this.name = name;
		}
		/**
		 * @return the hptDst
		 */
		public String getHptDst() {
			return hptDst;
		}
		/**
		 * @param hptDst the hptDst to set
		 */
		public void setHptDst(String hptDst) {
			this.hptDst = hptDst;
		}
		/**
		 * @return the genre
		 */
		public String getGenre() {
			return genre;
		}
		/**
		 * @param genre the genre to set
		 */
		public void setGenre(String genre) {
			this.genre = genre;
		}
		/**
		 * @return the laenge
		 */
		public String getLaenge() {
			return laenge;
		}
		/**
		 * @param laenge the laenge to set
		 */
		public void setLaenge(String laenge) {
			this.laenge = laenge;
		}
		/**
		 * @return the filmDat
		 */
		public String getFilmDat() {
			return filmDat;
		}
		/**
		 * @param filmDat the filmDat to set
		 */
		public void setFilmDat(String filmDat) {
			this.filmDat = filmDat;
		}
		
		
	}

}
